package beer.coder.walawala.gui.component;

import beer.coder.walawala.common.config.TabConfigure;
import java.util.function.Consumer;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Pos;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.input.MouseButton;
import javafx.scene.layout.StackPane;
import javafx.scene.text.TextAlignment;

/**
 * 仿Tab标签页
 *
 * @author amath0312
 * @version 1.0
 * @date 2019-10-23 20:59
 */
public class EditableLabel extends StackPane {

  private TabConfigure configure;

  private Label label;
  private TextField field;
  private String text;

  private Consumer<String> tabnameChangedHandler;

  public EditableLabel(String text) {
    super();
    this.text = text;
    init();
  }

  public EditableLabel() {
    this(null);
  }

  private void init() {
    this.setAlignment(Pos.CENTER);

    label = new Label(text);
    label.setTextAlignment(TextAlignment.CENTER);
    label.setAlignment(Pos.CENTER);
    field = new TextField(text);
    field.setAlignment(Pos.CENTER);

    this.getChildren().add(label);

    label.setOnMouseClicked(
        event -> {
          if (event.getClickCount() == 2 && event.getButton() == MouseButton.PRIMARY) {
            this.getChildren().clear();
            this.getChildren().add(field);
            field.selectAll();
            field.requestFocus();

            event.consume();
          }
        });
    field.setPickOnBounds(true);
    field
        .focusedProperty()
        .addListener(
            (observable, oldValue, newValue) -> {
              if (!newValue) {
                onTabnameChanged();
              }
            });
    field.setOnKeyReleased(
        event -> {
          if (event.getCode() == KeyCode.ESCAPE) {
            onTabnameCanceled();
          } else if (event.getCode() == KeyCode.ENTER) {
            onTabnameChanged();
          }
        });
    field
        .focusedProperty()
        .addListener(
            (observable, oldValue, newValue) -> {
              if (!newValue) {
                setText(field.getText());
                this.getChildren().clear();
                this.getChildren().add(label);
              }
            });
  }

  public void setContextMenu(ContextMenu ctx) {
    this.label.setContextMenu(ctx);
  }

  private void onTabnameChanged() {
    setText(field.getText());
    this.configure.setName(field.getText());
    if (this.tabnameChangedHandler != null) {
      this.tabnameChangedHandler.accept(field.getText());
    }
    this.getChildren().clear();
    this.getChildren().add(label);
  }

  private void onTabnameCanceled() {
    setText(this.text);
    this.getChildren().clear();
    this.getChildren().add(label);
  }

  public void setOnTabnameChanged(Consumer<String> handler) {
    this.tabnameChangedHandler = handler;
  }

  @Override
  protected void setWidth(double value) {
    super.setWidth(value);
    label.setPrefWidth(value);
    field.setPrefWidth(value);
  }

  @Override
  protected void setHeight(double value) {
    super.setHeight(value);
    label.setPrefHeight(value);
    field.setPrefHeight(value);
  }

  @Override
  public void setPrefSize(double prefWidth, double prefHeight) {
    super.setPrefSize(prefWidth, prefHeight);
    label.setPrefSize(prefWidth, prefHeight);
    field.setPrefSize(prefWidth, prefHeight);
  }

  public void setText(String text) {
    this.text = text;
    label.setText(text);
    field.setText(text);
  }

  public void restoreTabStyle() {
    this.setStyle(configure.getTabStyle());
  }

  public void selectedStyle() {
    this.setStyle(configure.getTabSelectedStyle());
  }

  public TabConfigure getConfigure() {
    return configure;
  }

  public void setConfigure(TabConfigure configure) {
    this.configure = configure;
  }
}
